package com.starblink.search.search.ui.fragment

import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.blankj.utilcode.util.KeyboardUtils
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxItemDecoration
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import com.starblink.android.basic.adapter.MutableAdapter
import com.starblink.android.basic.appsflyer.AppsflyerManager
import com.starblink.android.basic.base.fragment.BaseTVMFragment
import com.starblink.android.basic.ext.gone
import com.starblink.android.basic.ext.inflater
import com.starblink.android.basic.ext.string
import com.starblink.android.basic.ext.visible
import com.starblink.android.basic.ext.visibleOrGone
import com.starblink.android.basic.extension.dp2px
import com.starblink.android.basic.extension.lazyOnNone
import com.starblink.android.basic.extension.navigation
import com.starblink.android.basic.extension.navigationTo
import com.starblink.android.basic.sensorsdata.room.entity.SkAntEntity
import com.starblink.android.basic.sensorsdata.spm.GTrackerAssistUtils
import com.starblink.android.basic.sensorsdata.spm.cfg.SpmElementDef
import com.starblink.android.basic.sensorsdata.spm.cfg.SpmPageDef
import com.starblink.android.basic.sensorsdata.spm.impl.SpmTrackHandler
import com.starblink.android.basic.util.bus.FlowBus
import com.starblink.android.basic.util.bus.FlowConst
import com.starblink.android.basic.util.bus.bean.FollowStoreEvent
import com.starblink.android.basic.util.post.CommonMutateManage
import com.starblink.android.basic.widget.ConfirmDialog
import com.starblink.basic.apollo.ext.ApolloValSetExt
import com.starblink.basic.apollo.ext.ApolloValSetExt.apolloValue
import com.starblink.basic.route.RoutePage
import com.starblink.basic.style.R
import com.starblink.basic.style.view.recyclerview.SimpleGapItemDecor
import com.starblink.rocketreserver.fragment.MerchantWebVOF
import com.starblink.rocketreserver.fragment.SearchWordVOF
import com.starblink.search.config.SearchConfig
import com.starblink.search.databinding.CellRecommendStoreBinding
import com.starblink.search.databinding.CellSearchHotwordBinding
import com.starblink.search.databinding.CellSearchSugBinding
import com.starblink.search.databinding.FragmentSearchHomeBinding
import com.starblink.search.search.ui.SearchTVMActivity
import com.starblink.search.search.ui.cell.HistoryAdapter
import com.starblink.search.search.ui.cell.RecommendStoreCell
import com.starblink.search.search.ui.cell.SearchHotwordCell
import com.starblink.search.search.ui.cell.SearchSugAdapter
import com.starblink.search.search.ui.cell.SearchSugCell

/**
 * 搜索主页
 * @note 用户可以输入搜索关键字，通过Recently Viewed、Trending Topics、Search Suggestions等方式进行搜索
 */
internal class SearchHomeFragment() :
    BaseTVMFragment<FragmentSearchHomeBinding, SearchHomeFragmentVM>() {
    internal var homeHint: SearchWordVOF? = null
    internal var hotWords: List<SearchWordVOF>? = null
    internal var searchAction: ((searchWord: String, composeSearchWord: List<String>?, SearchWordSource: Int, goodsRuleId: String?) -> Unit)? =
        null

    internal var scene = RoutePage.Search.SCENE.NORMAL

    internal var historyTag: String = ""

    /**搜索建议Adapter（用户边输入边显示搜索建议）*/
    private val sugAdapter by lazyOnNone {
        SearchSugAdapter(viewModel.sugWordList).apply {
            addVhDelegate {
                SearchSugCell(
                    CellSearchSugBinding.inflate(
                        layoutInflater,
                        it,
                        false
                    )
                ) { sugWord, buttonWord ->
                    if (buttonWord.isNullOrEmpty()) {
                        doSearchAction(sugWord)
                    } else {
                        doSearchAction(
                            "$sugWord $buttonWord",
                            composeSearchWord = arrayListOf(sugWord, buttonWord)
                        )
                    }
                }
            }
        }
    }

    /**Recently Viewed Adapter（搜索历史）*/
    private val historyAdapter by lazyOnNone {
        HistoryAdapter(viewBinding.recyclerHistory, viewModel.history) {
            doSearchAction(it, searchWordSource = SearchConfig.SearchWordSourceConfig.O_TYPE_HIS)
        }
    }

    /**Trending Topics Adapter(热点主题)*/
    private val hotwordAdapter by lazyOnNone {
        MutableAdapter(viewModel.hotwordShownList).apply {
            addVhDelegate { it ->
                SearchHotwordCell(CellSearchHotwordBinding.inflate(it.inflater, it, false)) {
                    doSearchAction(
                        it.showWord,
                        searchWordSource = SearchConfig.SearchWordSourceConfig.O_TYPE_HOT
                    )
                }
            }
        }
    }

    /**Top stores to follow Adapter*/
    private val storeAdapter by lazyOnNone {
        MutableAdapter(viewModel.storeList).apply {
            addVhDelegate {
                RecommendStoreCell(
                    CellRecommendStoreBinding.inflate(
                        it.inflater,
                        it,
                        false
                    )
                ) { model, position ->
                    CommonMutateManage.subscribeOrNotMerchant(
                        requireContext(),
                        merchantId = model.id,
                        merchantName = model.merchantName ?: "",
                        subOrNot = model.subOrNot,
                        scope = lifecycleScope,
                        refreshState = {
                            ApolloValSetExt.setApolloVal<MerchantWebVOF>(
                                model,
                                "subOrNot",
                                model.subOrNot.not()
                            )
                            refreshStore(position)
                        }
                    )
                }
            }
        }
    }

    override fun getViewBinding(
        inflater: LayoutInflater,
        container: ViewGroup?,
    ) = FragmentSearchHomeBinding.inflate(inflater, container, false)


    override fun initView(view: View) {
        super.initView(view)
        viewBinding.searchInput.apply {
            onCameraIconTap = {
                SpmTrackHandler.addSingleTrackData(
                    SkAntEntity(
                        spmCnt = GTrackerAssistUtils.fetchElementValue(
                            SpmPageDef.SearchRoute,
                            SpmElementDef.HomeNewCameraClick_33001,
                        )
                    )
                )

                navigation(RoutePage.ImageSearch.PAGE_CAMERA)
            }
            onSearchActionDone = { it ->
                val params = mutableMapOf(
                    "searchTerm" to (if (it.isNullOrEmpty() && homeHint != null) (homeHint?.actualWord
                        ?: homeHint?.showWord ?: "") else it.toString()),
                )
                // 埋点：用户点击搜索按钮，使用 用户输入关键字 或者 搜索输入框底纹词 进行搜索
                SpmTrackHandler.addSingleTrackData(
                    SkAntEntity(
                        spmCnt = GTrackerAssistUtils.fetchElementValue(
                            SpmPageDef.SearchRoute,
                            SpmElementDef.SearchKeyword,
                        ),
                        params = params
                    )
                )
                AppsflyerManager.reportSearch(params)

                if (it.isNullOrEmpty() && homeHint != null) {
                    doSearchAction(
                        searchContent = homeHint?.actualWord?.ifEmpty { homeHint?.showWord },
                        searchWordSource = SearchConfig.SearchWordSourceConfig.O_TYPE_SHADING
                    )
                } else {
                    doSearchAction(searchContent = it)
                }
                KeyboardUtils.hideSoftInput(activity)
            }
            addTextChangedListener(
                afterTextChanged = { it ->
                    sugAdapter.curKeyword = it?.toString()
                    viewModel.curKeyword = it?.toString()
                    viewModel.subWordJob?.cancel()
                    if (viewModel.curKeyword.isNullOrEmpty()) {
                        viewModel.sugWordList.clear()
                        sugAdapter.refreshAll()
                        viewBinding.llSugs.gone()
                    } else {
                        viewModel.curKeyword?.takeIf { it.isNotEmpty() }?.let {
                            viewModel.textChangeTimeTag = System.currentTimeMillis()
                            viewModel.fetchSugWords(it)
                        }
                    }
                    viewModel.requestPreKeyWord = sugAdapter.curKeyword
                }
            )
        }
        viewBinding.recyclerSugs.adapter = sugAdapter
        viewBinding.recyclerSugs.layoutManager = LinearLayoutManager(requireContext())
        homeHint?.let {
            viewBinding.searchInput.hint =
                if (it.actualWord?.isNotEmpty() == true) it.actualWord else {
                    it.showWord.ifEmpty { string(com.starblink.basic.style.R.string.search_hint) }
                }
        }

        viewBinding.recyclerHistory.layoutManager = FlexboxLayoutManager(requireContext()).apply {
            flexDirection = FlexDirection.ROW
            justifyContent = JustifyContent.FLEX_START
            maxLine = 10
            flexWrap = FlexWrap.WRAP
            // alignContent = AlignContent.FLEX_END // not support
        }
        viewBinding.recyclerHistory.addItemDecoration(FlexboxItemDecoration(requireContext()).apply {
            setDrawable(object : ColorDrawable(Color.TRANSPARENT) {
                override fun getIntrinsicWidth(): Int = 8.dp2px()
                override fun getIntrinsicHeight(): Int = 8.dp2px()
            })
        })
        viewBinding.recyclerHistory.adapter = historyAdapter

        viewBinding.recyclerStore.layoutManager =
            LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
        viewBinding.recyclerStore.addItemDecoration(
            SimpleGapItemDecor(
                withEdge = false,
                horGap = 4.dp2px(),
            )
        )
        viewBinding.recyclerStore.adapter = storeAdapter
        viewBinding.btnStoreRetry.setOnClickListener {
            viewModel.queryRecStore()
        }

        viewBinding.btnTrendRetry.setOnClickListener {
            viewModel.refreshHotWord()
        }
        viewBinding.recyclerTrend.isNestedScrollingEnabled = false
        viewBinding.recyclerTrend.adapter = hotwordAdapter
        viewBinding.recyclerTrend.layoutManager = GridLayoutManager(requireContext(), 1)
        viewBinding.recyclerTrend.addItemDecoration(
            SimpleGapItemDecor(
                withEdge = false,
                horGap = 8.dp2px(),
                verGap = 10.dp2px()
            )
        )

        viewBinding.btnDelete.setOnClickListener {
            ConfirmDialog.Builder(requireContext())
                .setCancelButton(R.string.cancel) { dialog, _ ->
                    dialog.dismiss()
                }
                .setSureButton(R.string.confirm) { dialog, _ ->
                    viewModel.clearHistory()
                    dialog.dismiss()
                }
                .setTitle(R.string.clear_recent_view)
                .create().show()
        }
    }

    override fun initData() {
        viewModel.historyTag = historyTag
        viewModel.scene = scene
        viewModel.queryRecStore()
        viewModel.queryHistory()
        if (hotWords.isNullOrEmpty()) {
            viewModel.queryHotWord()
        } else {
            viewModel.hotwordList.addAll(hotWords!!)
            viewModel.refreshHotWord()
            viewModel.hotwordLD.postValue(hotWords!!.isNotEmpty())
        }

    }

    override fun startObserve() {
        viewModel.storeLD.observe(this) {
//            viewBinding.groupStore.visibleOrGone(it) {
//                storeAdapter.refreshAll()
//            }
        }
        viewModel.historyLD.observe(this) {
            viewBinding.groupHistory.visibleOrGone(it) {
                historyAdapter.notifyItemRangeChanged(0, historyAdapter.itemCount)
            }
        }
        viewModel.hotwordLD.observe(this) {
            viewBinding.groupTrend.visibleOrGone(it) {
                hotwordAdapter.notifyItemRangeChanged(0, hotwordAdapter.itemCount)
            }
        }
        viewModel.sugWordsLD.observe(this) {
            if (it) {
                viewBinding.llSugs.visible()
                sugAdapter.refreshAll()
            } else {
                viewBinding.llSugs.gone()
            }
        }

        FlowBus.with<FollowStoreEvent>(FlowConst.FOLLOW_STORE_EVENT).register(this) { event ->
            if (event.id != null) {
                viewModel.storeList.indexOfFirst { event.id == it.id }
                    .takeIf { it > -1 }?.let {
                        (viewModel.storeList[it] as? MerchantWebVOF?)?.apolloValue(
                            "subOrNot",
                            event.followed
                        )
                        storeAdapter.notifyItemChanged(it)
                    }
            }
        }
        viewModel.activityLoadingLD.observe(this.viewLifecycleOwner) {
            if (it) {
                (activity as? SearchTVMActivity)?.showDialogLoading()
            } else {
                (activity as? SearchTVMActivity)?.dismissDialogLoading()
            }
        }
    }

    private fun refreshStore(position: Int? = null) {
        if (position != null) {
            storeAdapter.notifyItemChanged(position)
        } else {
            storeAdapter.refreshAll()
        }
    }

    override fun onResume() {
        super.onResume()
    }

    internal fun saveQuery(word: String) {
        viewModel.saveHistory(word)
    }

    private fun doSearchAction(
        searchContent: CharSequence?,
        composeSearchWord: List<String>? = null, // 组合词，只有通过搜索建议获取搜索词时传入
        searchWordSource: Int = SearchConfig.SearchWordSourceConfig.O_TYPE_INPUT, // 搜索词来源
    ) {
        if (searchContent.isNullOrEmpty()) return
        val searchWord = searchContent.toString()
        saveQuery(searchWord)
        if (searchWord == "guang_up") {
            navigationTo(RoutePage.GCONFIG.GUANG_UP_CONFIG)
            viewModel.refreshHistory()
        } else {
            if (composeSearchWord?.isNotEmpty() == true) {
                searchAction?.invoke(searchWord, composeSearchWord, searchWordSource, null)
                viewModel.refreshHistory()
            } else {
                viewModel.fetchSearchWordConfig(searchContent.toString(), searchWordSource) {
                    if (!isAdded) return@fetchSearchWordConfig
                    when (it.jumpType) {
                        SearchConfig.SearchWordSourceConfig.JUMP_TYPE_H5, SearchConfig.SearchWordSourceConfig.JUMP_TYPE_NATIVE -> {
                            if (it.jumpUrl?.isNotEmpty() == true) {
                                navigationTo(url = it.jumpUrl)
                            } else {
                                searchAction?.invoke(
                                    it.actualWord.ifEmpty { searchWord },
                                    composeSearchWord,
                                    searchWordSource,
                                    it.goodsRuleId
                                )
                            }
                        }

                        else -> {
                            searchAction?.invoke(
                                it.actualWord.ifEmpty { searchWord },
                                composeSearchWord,
                                searchWordSource,
                                it.goodsRuleId
                            )
                        }
                    }
                    viewModel.refreshHistory()
                }
            }
        }
    }

    internal fun inputFocus(word: String?) {
        viewBinding.searchInput.requestFocus()
        viewBinding.searchInput.setText(word)
        viewBinding.searchInput.text?.let {
            viewBinding.searchInput.setSelection(it.length)
        }
        KeyboardUtils.showSoftInput()
    }

    companion object {


    }


}